# IteratorIterator.java

    package org.codefilarete.tool.collection;

    import java.util.Iterator;
    import java.util.NoSuchElementException;

    /**
     * An {@link Iterator} that iterates over other given {@link Iterator}s
     *
     * @author Guillaume Mary
     */
    public class IteratorIterator<E> implements Iterator<E> {

    	private final Iterator<Iterable<E>> iterables;

    	private Iterator<E> currentIterator;

    	@SafeVarargs // method body doesn't handle improperly varargs parameter so it would generate ClassCastException
    	public IteratorIterator(Iterator<E> ... iterables) {
    		// we wrap given iterator array into an array of iterables, no very cleanly done but it's a very local usage.
    		this(new Iterator<Iterable<E>>() {

    			private final Iterator<Iterator<E>> delegate = new ArrayIterator<>(iterables);

    			@Override
    			public boolean hasNext() {
    				return delegate.hasNext();
    			}

    			@Override
    			public Iterable<E> next() {
    				return delegate::next;
    			}
    		});
    	}

    	@SafeVarargs // method body doesn't handle improperly varargs parameter so it would generate ClassCastException
    	public IteratorIterator(Iterable<E> ... iterables) {
    		this(new ArrayIterator<>(iterables));
    	}

    	public IteratorIterator(Iterable<Iterable<E>> iterables) {
    		this(iterables.iterator());
    	}

    	public IteratorIterator(Iterator<Iterable<E>> iterables) {
    		this.iterables = iterables;
    	}

    	@Override
    	public boolean hasNext() {
    		if (currentIterator == null || !currentIterator.hasNext()) {
    			boolean found = false;
    			while(!found) {
    				if (iterables.hasNext()) {
    					currentIterator = iterables.next().iterator();
    					found = currentIterator.hasNext();
    				} else {
    					return false;
    				}
    			}
    		}
    		// here currentIterator != null && currentIterator.hasNext() or found = true => both conditions are always true
    		return true;
    	}

    	@Override
    	public E next() {
    		if (!hasNext()) {
    			throw new NoSuchElementException();
    		}
    		return currentIterator.next();
    	}

    	@Override
    	public void remove() {
    		currentIterator.remove();
    	}
    }